#include #include #include #include #include #include using namespace std; #define NUM_ADDRESSES_TO_GENERATE 10000 #define IN_BUFFER_SIZE 10 #define PAGE_SIZE 2048 #define MAIN_MEMORY_SIZE 16384 #define VIRTUAL_MEMORY_SIZE 65536 #define NUM_PAGES MAIN_MEMORY_SIZE / PAGE_SIZE int inBuffer[IN_BUFFER_SIZE]; // buffer to write/read virtual addresses int inBufferCount; // Number of virtual addresses in the shared buffer pthread_mutex_t inBufferMutex; // Mutex used to synchronize access to the inBuffer int numberOfPageFaults; // Counter for the number of page faults bool addressGenerationDone; // Flag used to indicate the address generation is done // TODO: You'll probably need some structures and variables to store information // needed for page replacement and address translation int getNextVirtualAddress(int addr) { // TODO: Replace below with your own method of generating virtual addresses. // You can just generate a random address if you want, which is probably the // easiest thing to do. return 0; } void* doAddressGeneration(void* pArg) { int addr = -1; int addressCount = NUM_ADDRESSES_TO_GENERATE; while (addressCount != 0) { if (inBufferCount < IN_BUFFER_SIZE) { addr = getNextVirtualAddress(addr); // Write the next virtual address. Be careful to synchronize // appropriately with the address translation thread. pthread_mutex_lock(&inBufferMutex); inBuffer[inBufferCount] = addr; inBufferCount++; pthread_mutex_unlock(&inBufferMutex); addressCount--; } else { // The buffer is full. Yield to wait for it to empty. sched_yield(); } } // Mark that address generation is done. addressGenerationDone = true; pthread_exit(NULL); } int translateAddress(int addr) { // TODO: See page 189 in the text for info about paging. You will need a page // table. I found Figure 3-10 useful. This figure shows how to translate a // virtual address to a physical address. // TODO: If the page table does not contain a mapping for to a page frame, a // page fault occurs. In this case, you will have to choose a page frame // (and possibly evict an old page if all page frames are in use). I would // recommend FIFO as the easiest to implement (see page 204). FIFO would // require a queue of page frames. return 0; } void* doAddressTranslation(void* pArg) { int addr; int physAddr; ofstream outputFile; ostream* pOutput; outputFile.open("ilab6_output.txt"); if (outputFile.is_open()) { pOutput = &outputFile; } else { cout << "Error opening ilab6_output.txt, using standard output" << endl; outputFile.close(); pOutput = &cout; } *pOutput << "Virtual -> Physical" << endl << "--------------------" << endl; // Keep translating addresses until none are left. while (!addressGenerationDone) { if (inBufferCount <= 0) { // There are no addresses to read. Yield to wait for more. sched_yield(); } while (inBufferCount > 0) { // Read the next virtual address. Be careful to synchronize // appropriately with the address generation thread. pthread_mutex_lock(&inBufferMutex); inBufferCount--; addr = inBuffer[inBufferCount]; pthread_mutex_unlock(&inBufferMutex); // Translate the virtual address. physAddr = translateAddress(addr); *pOutput << "0x" << hex << setfill('0') << setw(4) << addr << " -> 0x" << hex << setfill('0') << setw(4) << physAddr << endl; } } if (outputFile.is_open()) { outputFile.close(); } pthread_exit(NULL); } void* doStatistics(void* pArg) { pthread_t* pAddrTranThread = (pthread_t*)pArg; // Wait until address translation thread exits. pthread_join(*pAddrTranThread, NULL); cout << "Total Number of Page Faults = " << numberOfPageFaults << endl; pthread_exit(NULL); } int main(int argc, char* argv[]) { pthread_attr_t attrs; pthread_t addrGenThread; pthread_t addrTranThread; pthread_t statsThread; // TODO: Seed random number generator. If your getNextVirtualAddress // function does not generate random numbers, the following line can be // removed. srand(time(NULL)); pthread_mutex_init(&inBufferMutex, NULL); pthread_attr_init(&attrs); pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_JOINABLE); // Create three joinable threads, one for each component of the iLab. pthread_create(&addrGenThread, &attrs, doAddressGeneration, NULL); pthread_create(&addrTranThread, &attrs, doAddressTranslation, NULL); pthread_create(&statsThread, &attrs, doStatistics, &addrTranThread); pthread_attr_destroy(&attrs); pthread_join(addrGenThread, NULL); pthread_join(addrTranThread, NULL); pthread_mutex_destroy(&inBufferMutex); pthread_join(statsThread, NULL); // Once all the component threads have exited, the program can exit. return 0; }